/*数据供应高阶组件，封装数据请求的加载状态，错误，及结果的自动显示，调用方法如下:
@state (可选)设置页面初始状态 取值如下ViewState
@type (可选)设置状态页面功能类型，默认default，下拉刷新 refresh, 刷新列表 refreshList （包含下拉刷新，上拉加载）
@pageSize (可选)设置分页加载数，默认为10
@:params (可选)为请求函数initData传参
@immediate （可选）是否立即执行一次 默认true
@request (必填)Promise数据请求返回对象，暴露 params, {pageNum, pageSize}, context 三个对象参数，可获取高阶组件的params传参及分页对象参数，以及上下文context，用于手动访问高阶组件的内部状态和方法
@created (可选)暴露高阶组件内部created钩子及内部this对象
@mounted (可选)暴露高阶组件内部mounted钩子及内部this对象
@#default="{ data }" (必填)暴露的请求数据插槽对象，供模板调用
--------------------------------------
<provider
  :state="0"
  type="default"
  :pageSize = "10"
  :params="params"
  @request="request"
  #default="{ data }"
>
hello world, data={{data}}
</provider>

//request方法调用示例
setup(){
  const params = reactive({market:'ethusdt'})
  function request(params, {pageNum, pageSize}, context){ //params绑定参数，pageNum 传递当前分页， pageSize分页单页加载数，context高阶组件内部this对象
    return api.get(`api/v3/trade/market`, {data:{pageNum,pageSize}})
  }
  return {
    params,
    request
  }
}
--------------------------------------
*/
import FLoading from '@/components/FLoading'
import StateView from './provider_state_view'
import ViewState from './view_state.js'
import { onMounted, getCurrentInstance, watch, h } from 'vue'
import api from '@/api/request'
import { PullRefresh, List } from 'vant'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'

export default {
  install: (app, options) => {
    app.component('provider', {
      props: {
        params: {
          default: null
        },
        pageSize: {
          type: Number,
          default: 15
        },
        state: {
          type: [Number, String],
          default: null
        },
        immediate: {
          type: Boolean,
          default: true
        },
        type: String
      },
      setup(props, ctx) {
        const self = getCurrentInstance()
        const { t } = useI18n()
        const refreshing = ref(false) //刷新状态
        const loading = ref(false) //加载更多状态
        const isLoading = ref(false) //是否在加载状态
        const finished = ref(false) //是否加载完所有数据
        const pageNum = ref(1) //当前分页
        const viewState = ref(props.state<<0 || ViewState.idle) //页面状态
        const message = ref('') //状态信息
        const successText = ref('刷新成功') //刷新结果状态信息
        const data = ref(null) //数据请求结果
        let request = ctx.attrs.onRequest
        if (typeof request != 'function') {
          request = null
          console.error('Provider: request method no setting or not a function')
        }

        async function initData(init) { //init 是否第一次请求数据
          if (!request) {
            return
          }
          if (init) {
            viewState.value = props.state<<0 || ViewState.idle
          }
          let result = await request(props.params, { pageNum: pageNum.value, pageSize: props.pageSize }, self.ctx); //暴露组件变量传参params, 分页对象参数, 及组件上下文this对象
          switch (result.rst) {
            case api.SUCCESS:
              init && !result.data && (viewState.value = ViewState.empty)
              return result.data
            case api.UnAuthorized:
              message.value = `${result.code || ''} ${t('error_code.' + result.msg)}`
              init && (viewState.value = ViewState.unAuthorized)
              return
            default:
              message.value = `${result.code || ''} ${t('error_code.' + result.msg)}`
              init && (viewState.value = ViewState.error)
              return
          }
        }

        async function refresh(init = false) {
          pageNum.value = 1
          finished.value = false
          let _data = await initData(init);
          if (_data) {
            data.value = _data
            successText.value = '刷新成功'
            if (Array.isArray(_data)) {
              if (_data.length > 0) {
                init && (viewState.value = ViewState.idle)
                if (props.type == 'refreshList' && _data.length < props.pageSize) {
                  finished.value = true
                }
              } else {
                init && (viewState.value = ViewState.empty)
              }
            } else {
              init && (viewState.value = ViewState.idle)
            }
          } else {
            successText.value = '刷新失败'
          }
          refreshing.value = false

        }

        async function loadMore() {
          if (isLoading.value) {
            return
          }
          isLoading.value = true
          pageNum.value += 1
          let _data = await initData(false);
          if (!_data || _data.length == 0) {
            pageNum.value -= 1
            finished.value = true
          } else {
            data.value = data.value.concat(_data)
            if (_data.length < props.pageSize) {
              finished.value = true
            }
          }
          isLoading.value = false
          loading.value = false
        }

        function setBusy(value) {
          message.value = ''
          viewState.value = value ? ViewState.busy : ViewState.idle
        }

        function setEmpty(value) {
          message.value = '';
          viewState.value = ViewState.empty
        }

        function setError(value) {
          message.value = value;
          viewState.value = ViewState.error
        }

        function setUnAuthorized(value) {
          message.value = value ? t('未登录') : ''
          viewState.value = value ? ViewState.unAuthorized : ViewState.idle
        }

        props.immediate && refresh(true);
        if (typeof ctx.attrs.onCreated == 'function') {
          ctx.emit('created', self.ctx)
        }

        onMounted(() => {
          watch(
            () => props.params,
            () => { refresh(true) },
            { deep: true }
          )
          if (typeof ctx.attrs.onMounted == 'function') {
            ctx.emit('mounted', self.ctx)
          }
        })

        return {
          refreshing,
          successText,
          refresh,
          loading,
          finished,
          loadMore,
          viewState,
          message,
          data,
          context: self.ctx
        }
      },
      render() {
        return showViewByState(this)
      }
    })
  }
}


const showViewByState = function (context) {

  function getChild() {
    let child , slots = {...context.$slots}
    slots.default = ()=> context.$slots.default({ data: context.data })
    switch (context.type) {
      case 'refreshList':
        child = h(PullRefresh, {
          modelValue: context.refreshing,
          'onUpdate:modelValue': val => { context.refreshing = val },
          successText: context.$t(context.successText),
          onRefresh: () => context.refresh()
        }, {default:()=> h(List, {
          loading: context.loading,
          finished: context.finished,
          finishedText: context.$t('没有更多了'),
          immediateCheck: false,
          'onUpdate:loading': val => { context.loading = val },
          onLoad: () => context.loadMore()
        }, slots)})
        break
      case 'refresh':
        child = h(PullRefresh, {
          modelValue: context.refreshing,
          'onUpdate:modelValue': val => { context.refreshing = val },
          successText: context.$t(context.successText),
          onRefresh: () => context.refresh()
        }, slots)
        break
      default:
        child = slots
        break
    }
    return child
  }

  switch (context.viewState) {
    case ViewState.idle:
      return getChild()
    case ViewState.busy:
      return h(FLoading, { bgcolor: 'rgba(0, 0, 0, 0.32)', size: 40 })
    case ViewState.empty:
      return h(StateView, { context: context })
    case ViewState.error:
      return h(StateView, { image: require('@/assets/img/empty/empty-image-error.png'), buttonText: context.context.$t('重试'), context: context })
    case ViewState.unAuthorized:
      return h(StateView, { image: require('@/assets/img/empty/empty-image-error.png'), buttonText: context.context.$t('点击登录'), context: context })
    default:
      return []
  }
}
